1. /* sifiiadd.cpp by K.Tsuru */
  2. // function ID = 420
  3. // bugfix in version 2.16
  4. /****************************************
  5. SInteger class
  6. It provides the addition result = m + n.
  7. The signs of m and n can be different.
  8. **************************************/
  9. #ifndef SN_H
  10. #include "sn.h"
  11. #endif
  12. void IIAdd(const SInteger& m, const SInteger& n, SInteger& result){
  13. int s = m.Sign(420) * n.Sign(420), c;
  14. if(!s){
  15. if(!m.Sign()) result = n;
  16. else result = m;
  17. return;
  18. } else if(s < 0){ //different sign
  19. c = LLCompare(m, n);
  20. if(c > 0){ // m + n = m - (-n)
  21. // Notice the case "&result == &m" or "&result == &n".
  22. SInteger temp(n); // bugfix ver. 2.16 on Jul 31, 2002
  23. temp.ChangeSign(); //temp = -n
  24. IISub(m, temp, result); // |m| > |n|. The sign is the same as that of m.
  25. }else if(c < 0){ // m + n = n - (-m)
  26. SInteger temp(m); // bugfix ver. 2.16 on Jul 31, 2002
  27. temp.ChangeSign(); //temp = -m
  28. IISub(n, temp, result); // |m| < |n|. The sign is the same as that of m.
  29. } else result.SetZero(); // c = 0 : |m| = |n|
  30. return;
  31. }
  32. // m and n have the same sign.
  33. //It makes |m| >= |n|.
  34. if(m.Head() < n.Head()){ IIAdd(n, m, result); return; }
  35. // Here |m| > |n| ("c > 0 && mh >= nh") and evaluate m + n.
  36. // m and n have the same sign and the figures of m is greater than or equal to that of n.
  37. if(n.aHead == 0){ // n has one figure.
  38. // bugfix ver. 2.16
  39. if(n.Sign() > 0) IsAdd(m, n(0), result); // 0 < n < m, m + n = m + n(0)
  40. else IsSub(m, n(0), result); // m < n < 0, m + n = m - n(0)
  41. result.SetSign( m.Sign() );
  42. return;
  43. }
  44. uint mh = m.Head(), nh = n.Head(); // mh >= nh
  45. uint rt = min( m.Tail(), n.Tail() );
  46. /*
  47. Neither IIAdd(L, z, L); nor IIAdd(z, L, L);
  48. it allocates the memory of "result" and initializes it.
  49. */
  50. if( (&m != &result) && (&n != &result) ){
  51. result.valloc(m.Size(), -1);
  52. if(rt) result.figure.clear(0, rt -1u);
  53. result.figure.clear(mh+1u);
  54. } else result.Reserve(mh);//IIAdd(z, L, L); z > L(=result)
  55. const fType* mv = m.ReadFigures();
  56. const fType* nv = n.ReadFigures();
  57. fType* rv = result.figure.Elements();
  58. #ifndef NDEBUG
  59. result.figure(mh);
  60. #endif
  61. // rv[] = mv[] + nv[]
  62. fType u = 0; //carry = 0 or 1
  63. register uint i;
  64. for(i = rt; i <= nh ; i++) {
  65. u += mv[i] + nv[i];
  66. rv[i] = u & BRADIX1;
  67. u >>= BRADIX_BITS; // 0 or 1
  68. }
  69. //processing upper figures
  70. for( ; u && (i<= mh) ; i++){//A few times to u = 0 except special case.
  71. u += mv[i];
  72. rv[i] = u & BRADIX1;
  73. u >>= BRADIX_BITS;
  74. }
  75. if(u){ //One figure increases.
  76. mh++;
  77. result.Reserve(mh); // check over flow
  78. rv = result.figure.Elements(); //Reserve() maybe changed "rv".
  79. result.figure[mh] = u;
  80. } else if( (mh >= i) && (rv != mv) ){ //no carry
  81. memcpy(rv + i, mv + i, sizeof(fType)*(mh-i+1));
  82. }
  83. //It gets figure positions.
  84. while( !rv[rt] ) rt++;
  85. result.aHead = mh; result.aTail = rt;
  86. result.SetSign( m.Sign() );
  87. //If the figures decrease it reduces the size, considering the case that
  88. //IIAdd(m, n, result); result>m.
  89. if( 2u*(result.aHead+1) <= result.figure.size() ) result.DoCutDown();
  90. }

sifiiadd.cpp : last modifiled at 2017/03/13 14:31:59(3,143 bytes)
created at 2016/04/25 14:53:17
The creation time of this html file is 2017/10/25 11:09:45 (Wed Oct 25 11:09:45 2017).